package com.effectiv.gooruda.rest.service.impl;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import com.effectiv.gooruda.rest.domain.Cache;
import com.effectiv.gooruda.rest.domain.CacheEntry;
import com.effectiv.gooruda.rest.ext.ExtResponse;
import com.effectiv.gooruda.rest.service.api.CacheService;
import com.hazelcast.core.IMap;

@Slf4j
@Component
public class CacheServiceImpl extends CacheService {

	@Override
	public Response findOne(String cacheName) {

		log.info("Findone Cache Name = {}", cacheName);

		IMap<String, CacheEntry> map = getMap(cacheName);

		Cache cache = null;
		ExtResponse res = new ExtResponse();
		if (map != null) {
			cache = BeanUtils.instantiate(Cache.class);
			cache.setName(cacheName);
			cache.setSize(map.size());
			cache.setId(map.getId().toString());
			res.setId(cache.getId());
			res.setValue(cache);
		}

		GenericEntity<ExtResponse> entity = new GenericEntity<ExtResponse>(res,
				ExtResponse.class);

		ResponseBuilder builder = Response.ok(entity);

		return builder.build();

	}

	@Override
	public Response addEntry(String cacheName, String key, CacheEntry entry) {
		IMap<String, CacheEntry> map = getMap(cacheName);

		long timeout = entry.getTtl();

		Object o = entry.getValue();

		log.debug("o = {}", o);
		log.debug("o = {}", o.getClass());

		if (o instanceof Integer) {
			Integer i = (Integer) o;
			log.debug("Integer value = {}", i);

			entry.setValue(new AtomicInteger(i));
		}

		map.put(key, entry, timeout, TimeUnit.SECONDS);

		ExtResponse res = new ExtResponse();
		res.setMessage("Entry added in cache.");
		GenericEntity<ExtResponse> entity = new GenericEntity<ExtResponse>(res,
				ExtResponse.class);

		ResponseBuilder builder = Response.ok(entity);

		return builder.build();
	}

	@Override
	public Response getEntry(String cacheName, String key) {
		IMap<String, CacheEntry> map = getMap(cacheName);
		CacheEntry entry = map.get(key);

		ExtResponse res = new ExtResponse();
		res.setValue(entry);
		res.setMessage("Entry added in cache.");
		GenericEntity<ExtResponse> entity = new GenericEntity<ExtResponse>(res,
				ExtResponse.class);

		ResponseBuilder builder = Response.ok(entity);

		return builder.build();

	}

	@Override
	public Response delete(String cacheName) {
		IMap<String, CacheEntry> map = getMap(cacheName);
		Cache cache = null;
		ExtResponse res = new ExtResponse();
		if (map != null) {
			cache = BeanUtils.instantiate(Cache.class);
			cache.setName(cacheName);
			cache.setSize(map.size());
			cache.setId(map.getId().toString());

			map.destroy();
			res.setValue(cache);
		}

		res.setMessage("Cache with name - " + cacheName + " deleted.");
		GenericEntity<ExtResponse> entity = new GenericEntity<ExtResponse>(res,
				ExtResponse.class);

		ResponseBuilder builder = Response.ok(entity);

		return builder.build();
	}

	@Override
	public Response clear(String cacheName) {
		IMap<String, CacheEntry> map = getMap(cacheName);
		map.clear();

		ExtResponse res = new ExtResponse();
		res.setMessage("Cache with name - " + cacheName + " cleared.");
		GenericEntity<ExtResponse> entity = new GenericEntity<ExtResponse>(res,
				ExtResponse.class);

		ResponseBuilder builder = Response.ok(entity);

		return builder.build();
	}

	@Override
	public Response removeEntry(String cacheName, String key) {
		IMap<String, CacheEntry> map = getMap(cacheName);
		CacheEntry entry = map.remove(key);

		ExtResponse res = new ExtResponse();

		if (entry != null) {
			res.setMessage("Entry with key - " + key
					+ " deleted from cache with name - " + cacheName);
			res.setValue(entry);
		} else {
			res.setMessage("No Entry with key - " + key + " found on cache - "
					+ cacheName);
		}

		GenericEntity<ExtResponse> entity = new GenericEntity<ExtResponse>(res,
				ExtResponse.class);

		ResponseBuilder builder = Response.ok(entity);

		return builder.build();
	}

	@Override
	public Response increment(String cacheName, String key) {
		IMap<String, CacheEntry> map = getMap(cacheName);

		log.debug("Map = {}", map);

		CacheEntry entry = map.get(key);

		log.debug("entry = {}", entry);

		log.debug("value = {}", entry.getValue());
		
		ExtResponse res = new ExtResponse();
		
		try {

			((AtomicInteger) entry.getValue()).addAndGet(1);
		} catch (Exception e) {
			res.setErrorCode(401);
			res.setMessage("Error in incrementing the key value - " + e.getLocalizedMessage());
		}

		map.put(key, entry);
		
		res.setValue(entry);

		GenericEntity<ExtResponse> entity = new GenericEntity<ExtResponse>(res,
				ExtResponse.class);

		ResponseBuilder builder = Response.ok(entity);

		return builder.build();
	}

}
